/**************************************************************************
 *         Copyright(c) 2007 by Sunplus mMedia  Technology Co., Ltd.       *
 *                                                                         *
 *  This software is copyrighted by and is the property of Sunplus mMedia  *
 *  Technology Co., Ltd. All rights are reserved by Sunplus mMedia Techno- *
 *  logy Co., Ltd. This software may only be used in accordance with the   *
 *  corresponding license agreement. Any unauthorized use, duplication,    *
 *  distribution, or disclosure of this software is expressly forbidden.   *
 *                                                                         *
 *  This Copyright notice "M U S T" not be removed or modified without     *
 *  prior written consent of Sunplus mMedia Technology  Co., Ltd.          *
 *                                                                         *
 *  Sunplus mMedia Technology Co., Ltd. reserves the right to modify this  *
 *  software without notice.                                               *
 *                                                                         *
 *  Sunplus mMedia Technology Co., Ltd.                                    *
 *  19-1, Innovation First Road, Science-Based Industrial Park,            *
 *  Hsin-Chu, Taiwan, R.O.C.                                               *
 *                                                                         *
 **************************************************************************/
 #define __FILE		__FILE_ID_APP_INIT__
#include "general.h"
#include "initio.h"
#include "os_api.h"
#include "app_main.h"
#include "os_msg.h"
#include "main.h"
#include "audio.h"
#include "sp1k_bp_api.h"
#include "app_ui_para.h"
#include "app_menu.h"
#include "app_menu_micro.h"
#include "ptr_func.h"
#include "key_scan.h"
#include "app_ui_power.h"
#include "sp1k_pv_api.h"
#include "sp1k_snap_api.h"
#include "sp1k_aaa_api.h"
#include "sp1k_rsvblk_api.h"
#include "sp1k_disp_api.h"
#include "sp1k_front_api.h"
#include "sp1k_osd_api.h"
#include "sp1k_hal_api.h"
#include "sp1k_util_api.h"
#include "sp1k_cdsp_api.h"
#include "sp1k_aud_api.h"
#include "sp1k_cmd_api.h"
#include "sp1k_pb_api.h"
#include "app_audio_play.h"
#include "app_battery.h"
#include "sp1k_vfs_api.h"
#include "dramfunc.h"
#include "dos32.h"
#include "gpio_api.h"

/**************************************************************************
 *                           C O N S T A N T S                            *
 **************************************************************************/

/**************************************************************************
 *                              M A C R O S                               *
 **************************************************************************/

/**************************************************************************
 *                          D A T A    T Y P E S                          *
 **************************************************************************/

/**************************************************************************
 *                         G L O B A L    D A T A                         *
 **************************************************************************/

/**************************************************************************
 *                 E X T E R N A L    R E F E R E N C E S                 *
 **************************************************************************/
extern UINT8 xdata IOTrap;
extern UINT8 xdata G_SDCardPlug;//1:plugged in  0:no card
extern panelStatus_t G_PanelStatus;
extern xdata UINT8 G_calibrationMode;
extern xdata UINT8 exifVlcAtOdd;
UINT8 TV_Open=0;			

/**
 * @brief   mem init
 * @param	NULL
 * @retval	NULL
 * @see
 * @author	Phil Lin
 * @since	2008-02-20
 * @todo	Something need to be done.
 * @bug		a bug need to be resolved.
*/
void memInit(void)
{
	/* 
		NOTE: this function is called by function "main" firstly.
		Pls DO NOT add anything not important to this function!!!
	*/

	/* system memory block size initio (Absolute) */
	sysMemSizeInit();

	/* customize memory block size here */
	appMemDosRamInit();

	/* update the whole system memory address */
	sysMemAddrUpdate();	
}

/**
 * @brief		device init
 * @param	NULL
 * @retval	NULL
 * @see
 * @author	Phil Lin
 * @since		2008-02-20
 * @todo		Something need to be done.
 * @bug		a bug need to be resolved.
*/
void devInit(void) USING_0
{
	uiPara_t* puiPara;
	devAttr_t* pDevAttr;
	UINT16 decWidth, decHeight;
	UINT8 sensorId, panelId, ntscId, palId;


#if 1
#if (_HW_SOLUTION_ == _HW_EVB_)
	printf("\nEVB ");
#elif (_HW_SOLUTION_ == _HW_TK_MODEL_A_)
	printf("\nTK A ");
#elif (_HW_SOLUTION_ == _HW_TK_MODEL_B_)
	printf("\nTK B ");
#endif
	printf("F/W version is %s\nF/W compiled @ %s, %s\n\n", sp1kFWVerGet(), sp1kFWDateGet(), sp1kFWTimeGet());
#endif
	appGpioInit();
	INITIO_Initialize();

	/* MSDC initialize */
	#if (MLUN_OPTION)
	//if G_ucMSDC_MLUN = 1, First LUN = Build in
	//if G_ucMSDC_MLUN = 2, First LUN = Card
	G_ucMSDC_MLUN = 1;
	#else
	G_ucMSDC_MLUN = 0;
	#endif

	//if (sp1kDiskTypeGet() == DEV_TYPE_DISK_SPI){
	//	G_ucMSDC_MLUN = 0;
	//}

	appUiParaInit(PARA_INIT_FROM_UDF);
	puiPara = appUiParaGet();
	pDevAttr = sp1kDevHdlGet();

	sp1kHalCtrlScreen(0);

	appOpenImgShow(puiPara->StartupImage);

	sp1kPbDecodeSizeGet(&decWidth, &decHeight);
	sp1kDispPbBufSet(sp1kPbDispBuffGet(1), decWidth, decHeight);

	appBattInit();

#if (_HW_SOLUTION_ != _HW_EVB_)
	if (!prjDbgMode) {
		if (sp1kBtnChk(SP1K_BTN_POWER) != KEY_STATUS_PRESSED) {
			//printf("zhenglei....off 1\n");
			//appPowerShutDown();
		}
	}
#endif

	sp1kAudioVolumeSet(puiPara->Volume);
	sp1kAudioPlayInit();
	sp1kAudParamSet(SP1K_AUD_PARAM_ALC_DIGITAL_VOL,64);
	sp1kAudParamSet(SP1K_AUD_PARAM_ALC_OPT,1);
	//add for improving audio rec
	sp1kAudParamSet(SP1K_AUD_PARAM_ALC_MIN_VOL,15);
	sp1kAudParamSet(SP1K_AUD_PARAM_ALC_MAX_VOL,25);
	sp1kAudParamSet(SP1K_AUD_PARAM_ALC_DEFAULT_GAIN_IDX,32);
    sp1kAudParamSet(SP1K_AUD_PARAM_ALC_GAIN_DOWN_SPEED,0);
	sp1kAudParamSet(SP1K_AUD_PARAM_ALC_GAIN_UP_SPEED,40);
	//end add for improving audio rec
	/* init front. */
	sensorId = sp1kFrontSensorInit();
	sp1kFrontDevActSet(sensorId);
	sp1kFrontPowerOn(sensorId);

	/* init disp devices. */
	panelId = sp1kDispPanelInit();
	ntscId = sp1kDispTvNtscInit();
	palId = sp1kDispTvPalInit();
	//printf("panel=%d ntsc=%d pal=%d\n", (UINT16)panelId, (UINT16)ntscId, (UINT16)palId);

	if ( pDevAttr[DEV_ID_TV].devEn == 1
	&& pDevAttr[DEV_ID_TV].devSts == DEV_STS_CONNECTED ) {
		TV_Open = 1;                       //SUN 20090514
		sp1kAudioVolumeSet(puiPara->Volume );
		if ( puiPara->TVMode == TVMODE_NTSC ) {
			sp1kDispDevActSet(ntscId);
			sp1kDispPowerOn(ntscId);
			pDevAttr[DEV_ID_TV].devType = DEV_TYPE_TV_NTSC;
			G_PanelStatus= PANEL_STATUS_NTSC;
		}
		else {
			sp1kDispDevActSet(palId);
			sp1kDispPowerOn(palId);
			pDevAttr[DEV_ID_TV].devType = DEV_TYPE_TV_PAL;
			G_PanelStatus= PANEL_STATUS_PAL;
		}
		pDevAttr[DEV_ID_TV].devSts = DEV_STS_RDY;
	}
	else {
		sp1kDispDevActSet(panelId);
		sp1kDispPowerOn(panelId);
	}

	if (puiPara->StartupImage) {
		sp1kHalJpegDecodeWait();
		sp1kHalDispScaleSet(decWidth, decHeight, 100);
		sp1kHalCtrlScreen(1);
	}

	if(pDevAttr[DEV_ID_PANEL].devEn == 1) {
		sp1kHalDisplayEnable();
	}

	appVoicePlay(SP1K_MSG_UNKNOWN, VOICE_TYPE_OPEN, VOICE_PLAYLEVLE_HIGH);

	sp1kRTCInit();
	appButtonInit();
}

//-----------------------------------------------------------------------------
//appInit
//-----------------------------------------------------------------------------
/**
 * @brief		application init
 * @param	NULL
 * @retval	NULL
 * @see
 * @author	Phil Lin
 * @since		2008-02-20
 * @todo		Something need to be done.
 * @bug		a bug need to be resolved.
*/
void appInit(void) USING_0
{
	osInit();
	osMsgInit();
	sp1kCmdInit();

	osTaskCreate(osTaskIdle, OS_PRIO_ACTIVE_FUNC);
	osTaskCreate(pFunc_CardDetect, OS_PRIO_CARD);
	if(pkgChipIdGet() != 0x1527){ //SUN 20090514
	osTaskCreate(pFunc_USBDetect, OS_PRIO_USB);
	osTaskCreate(pFunc_TVDetect, OS_PRIO_TV);
	}
#ifdef WHITE_LED
	osTaskCreate(pFunc_whiteLedCtrl, OS_PRIO_CARD);
#endif

	if (DOS_DosRamStsGet() == TRUE) {
		sp1kDosRamBufSet(K_SDRAM_DosRamBufSize);
	}

	sp1kSnapInit( 8, K_SDRAM_CommonEndAddr, K_SDRAM_TotalSize );
	//sp1kSnapInit( 8, (UINT32)K_SDRAM_CommonEndAddr + dosRamSize, (UINT32)K_SDRAM_TotalSize );

	sp1kSnapCallbackReg( SP1K_SNAP_CALLBACK_BURST, pFunc_SnapBurst );

	IOTrap = sp1kHalReadIOTrap();
	printf("IOTrap %bx\n",IOTrap);

	if(IOTrap == 0x98) { // Nor flash boot
		sp1kHaRomShadowToDram();
	}
	//Shadow_ImemTest();
	//printf("zhenglei....1\n");
	sp1kHalDramShadowToImem();
	//printf("zhenglei....2\n");

	/* init osd. */
	sp1kOsdLoad();
	//printf("zhenglei....3\n");
	sp1kOsdInit(appPanelTypeGet());
	//printf("zhenglei....4\n");
	sp1kOsdFontSizeSet(16, 32); /* Should be (16, 32), (12, 24), (8, 16) */
	//printf("zhenglei....5\n");
	sp1kHalCtrlScreen(3);
	//printf("zhenglei....6\n");
	/* Load power control parameters */
	sp1kNandRsvRead(0x14, (K_SDRAM_PwrCtrlParameterBuf << 1));
	//printf("zhenglei....7\n");

	/* Load usb customize strings */
	//sp1kNandRsvRead(0x0C, (K_SDRAM_CommonEndAddr << 1));
	sp1kUsbStrSet(/*K_SDRAM_CommonEndAddr*/0x0c);

#ifdef LOAD_CDSP_PARAMETER_BIN
	if( G_calibrationMode == 0 ) {
		sp1kCDSPParaInit( 0x09 );
		sp1kCDSPGammaParaInit( 0x08 );
		sp1kCDSPLcInit( 0x07 );
#if 0
		XBYTE[ 0x2130 ] = 0x01;
#endif
	}
#endif

	sp1kCDSPInit();
	//printf("zhenglei....8\n");
#ifdef LOAD_AWBCTT_BIN
	sp1kNandRsvRead(0x04, K_SDRAM_AWBCTT_Buf_Address);
	/*
	{
		UINT32 i;
		printf("#");
		for (i=0;i<32;i++){
			printf("%bx ",XBYTE[0x7400+i]);
		}
	}
	*/
#endif
	//printf("zhenglei....9\n");
	/* badpixel compensation resource file loading */
	if ( sp1kBpResCfg(RES_BP_PRV, 0x05) == SUCCESS ) {
		if ( sp1kBpResLoad(RES_BP_PRV, K_SDRAM_BadPixelCoordBufAddr) != 0 ) {
			sp1kBpPrvAddrSet(K_SDRAM_BadPixelCoordBufAddr);
			sp1kBpPrvEn(1);
		}
	}
	if ( sp1kBpResCfg(RES_BP_CAP, 0x06) == SUCCESS ) {
		if ( sp1kBpResLoad(RES_BP_CAP, K_SDRAM_BadPixelCoordBufAddr + K_SDRAM_BadPixel_PrvBufSize) != 0 ) {
			sp1kSnapParamSet(SP1K_SNAP_PARAM_BAD_PIXEL_OPT, 1);
		}
	}
	//printf("zhenglei....10\n");
	sp1kAwbParaInit( (UINT8)0x04 );

/**********************OB Calibration for OV5620************************/
#if 0//(SENSOR_TYPE == Sensor_OV5620)	//cleaer warning
	printf("OV5620 OB\n");

	//First : OB check
	if (0)//unchecked
	{
		sp1kOsdStrDraw(1,1,"OB Calibration",0);

		//Calibration flow

		if (1)//calibration fail
		{
			sp1kOsdStrDraw(1,1,"OB Calibration Fail",0);
			//delay 5ms
			//power off
		}
	}
#endif/*SENSOR_TYPE == Sensor_OV5620*/
	printf("zhenglei....11\n");
	sp1kAeAwbInit();
	printf("zhenglei....12\n");
	osMsgPost(SP1K_MSG_STATE_TO_POWER_ON);
	printf("zhenglei....13\n");
}

//-----------------------------------------------------------------------------
//appButtonInit
//-----------------------------------------------------------------------------
/**
 * @brief		button init
 * @param	NULL
 * @retval	NULL
 * @see
 * @author	Phil Lin
 * @since		2008-02-20
 * @todo		Something need to be done.
 * @bug		a bug need to be resolved.
*/
void appButtonInit(void) USING_0
{
	devAttr_t* pDevAttr;

	sp1kAdcInit();

	sp1kBtnDisableAll();

 	pDevAttr = sp1kDevHdlGet();
	pDevAttr[DEV_ID_KEYBROAD].devSts = DEV_STS_RDY;
	pDevAttr[DEV_ID_KEYBROAD].devEn = 1;
	pDevAttr[DEV_ID_KEYBROAD].devType = DEV_TYPE_KEYBROAD_COM;

	TIMER0_Start();
}

//-----------------------------------------------------------------------------
//appOpenImgShow
//-----------------------------------------------------------------------------
/**
 * @brief	       decode start up image
 * @param	NULL
 * @retval	NULL
 * @see
 * @author	Phil Lin
 * @since		2008-02-20
 * @todo		Something need to be done.
 * @bug		a bug need to be resolved.
*/
UINT8 appOpenImgShow(UINT8 mode) USING_0
{
	UINT32 freeBuffAddr = K_SDRAM_ImagePlaybackBufAddr;
	UINT16 decWidth = PB_DECODE_WIDTH;
	UINT16 decHeight = PB_DECODE_HEIGHT;
	UINT32 decBuff = K_SDRAM_ImagePlaybackBufAddr;
	UINT8 resID;

	if (mode == PB_OPENPIC_OFF) {
		/* open image function is disabled */
		sp1kPbDecodeSizeSet(decWidth, decHeight);
		sp1kPbDispBuffSwitch();
		decBuff = sp1kPbDispBuffGet(1);
		
		sp1kPbFillBlack(decBuff, decWidth, decWidth);
		return SUCCESS;		
	} else if (mode == PB_OPENPIC_USER_DEF) {
		/* specify user defined startup image */
		resID = 0x81;
	} else {
		/* specify the default startup image */
		resID = 0x0d;
	}

	/* set decode size */
	sp1kPbDecodeSizeSet(decWidth, decHeight);
	sp1kPbDispBuffSwitch();

	/* start-up image decode process */
	appBGImgDec(resID, NULL, freeBuffAddr, sp1kPbDispBuffGet(1), 0);

	return SUCCESS;
}

//-----------------------------------------------------------------------------
//sp1kGpioInit
//-----------------------------------------------------------------------------
/**
 * @brief		sp1k gpio config
 * @param	NONE
 * @retval	NONE
 * @see
 * @author	sun yong
 * @since		2008-03-01
 * @todo		Something need to be done.
 * @bug		NONE.
*/
void appGpioInit(void)
{
	//only for 1527 debug @090520
	sp1kDebugModeSet_1527(NORMAL_MODE);
	
#if(_HW_SOLUTION_ == _HW_TK_MODEL_B_)
	//enable speaker
	sp1kSpeaker_ENCfg();
#endif
	sp1kSDWriteProtectDetectConfig();
	sp1kTV_PlugCfg(TV_PLUG, 0);
	
	pullEnSet(2, 0x10, 0); // disable gpio 2 internal pull  
	sp1kUSB_PlugCfg();
	//Add for card detect polarity seting
	sp1kSD_CD_PolaritySet(0);
	sp1kSD_CdCfg();

	//if slect LED function
	sp1kLED_SelfCfg();
	sp1kLED_SelfSet(1);
	///
	sp1kLED_BusyCfg();
	sp1kLED_BusySet(1);//turn off status led
}

void appMemDosRamInit(void)
{
	UINT32 totSize = sysMemTotSizeGet();
	UINT32 size;
	UINT8 enable; /* the switch for dos ram function */

	switch (totSize) {		
		case DEV_MEM_SIZE_16M:
		case DEV_MEM_SIZE_64M:
			size = 0;
			enable = 0;
			break;
		case DEV_MEM_SIZE_128M: 
			size = 0x400000; //4M Word
			enable = 1;
			break;
		case DEV_MEM_SIZE_256M: 
			size = 0xC00000; //12M Word
			enable = 1;
			break;
		case DEV_MEM_SIZE_512M: 
			size = 0x1400000; //20M Word
			enable = 1;
			break;
		default:
			size = 0;
			enable = 0;
			break;
	}
	
#ifndef DISK_DRV_DRAM
	size = 0;
	enable = 0;
#endif

	DOS_DosRamCfg(enable);
	sysMemSizeSet(MEM_IDX_DOS_RAM, size);
}
